<?php
/*
Plugin Name: WooCommerce PayPal Payflow Pro Gateway
Plugin URI: http://ignitewoo.com
Description: Extends WooCommerce with a <a href="https://www.paypal.com" target="_blank">PayPal Payflow Pro</a> gateway. A PayPal Payflow Pro gateway account, and a server with SSL support and an SSL certificate is required for security reasons.
Version: 1.3.1
Author: IgniteWoo.com
Author URI: http://ignitewoo.com
*/

/*

Copyright (c) 2012 - 2013 IgniteWoo.com - ALL RIGHTS RESERVED

This plugin comes with a single site license - unless you purchased
a multisite license. Please support us and help create more great plugins
by buying a license for each site that you use it on.

The software is distrbuted WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. You use this software at your own risk.


*/


add_action( 'plugins_loaded', 'woocommerce_payflow_init', 0 );

function woocommerce_payflow_init() {

	if ( !class_exists('woocommerce_payment_gateway' ) ) return;
	

	/**
	* Required functions
	*/
	if ( ! function_exists( 'ignitewoo_queue_update' ) )
		require_once( dirname( __FILE__ ) . '/ignitewoo_updater/ignitewoo_update_api.php' );

	$this_plugin_base = plugin_basename( __FILE__ );

	add_action( "after_plugin_row_" . $this_plugin_base, 'ignite_plugin_update_row', 1, 2 );


	/**
	* Plugin updates
	*/
	ignitewoo_queue_update( plugin_basename( __FILE__ ), '73c3b72bc6c62aba84eba57ea98160ae', '52' );



	define('PAYFLOW_DIR', WP_PLUGIN_DIR . "/" . plugin_basename( dirname( __FILE__ ) ) . '/');

	// Add the gateway to the list of available payment gateway 
	add_filter( 'woocommerce_payment_gateways', 'add_flowpro_gateway' );
	function add_flowpro_gateway( $methods ) { 
		$methods[] = 'woocommerce_flowpro'; 
		return $methods;

	}


	// Payflow Pro payment class
	class woocommerce_flowpro extends woocommerce_payment_gateway {

		public function __construct() { 

			$this->id		= 'flowpro';

			// $this->supports = array( 'products', 'subscriptions', 'subscription_cancellation'  );

			$this->icon 		= WP_PLUGIN_URL . "/" . plugin_basename( dirname(__FILE__) ) . '/images/cards.png';

			$this->has_fields 	= false;
					
			$this->init_form_fields();
			
			$this->init_settings();

			$this->enabled 		= $this->settings['enabled'];
			$this->title 		= $this->settings['title'];
			$this->description	= $this->settings['description'];
			$this->partnername	= $this->settings['partnername'];
			$this->username		= $this->settings['username'];
			$this->password		= $this->settings['password'];
			$this->vendorname	= $this->settings['vendorname'];
			$this->processing_type	= $this->settings['processing_type'];
			$this->testmode		= $this->settings['testmode'];
			$this->gateway_url	= '';
			$this->debug		= $this->settings['debug'];
			$this->debugrecipient 	= $this->settings['debugrecipient'];
			$this->cvv		= $this->settings['cvv'];
			$this->cardtypes	= $this->settings['cardtypes'];

			add_action( 'admin_notices', array( &$this,'flowpro_net_ssl_check' ) );

			add_action( 'admin_notices', array( &$this,'curl_check' ) );

			add_action( 'woocommerce_update_options_payment_gateways', array( &$this, 'process_admin_options' ) );

			add_action( 'woocommerce_receipt_flowpro', array( &$this, 'receipt_page' ) );

			//add_filter( 'woocommerce_subscription_periods', array( &$this, 'woocommerce_subscription_periods' ), 999, 1 );

			//add_action( 'cancelled_subscription_flowpro', array( &$this, 'cancel_subscription' ), 1, 2 );


		} 


		// SSL check
		function flowpro_net_ssl_check() {
			
			if (get_option('woocommerce_force_ssl_checkout')=='no' && $this->enabled=='yes')
			    echo '<div class="error"><p>'.sprintf(__('PayPal Payflow Pro is enabled and the <a href="%s">force SSL option</a> is disabled; your checkout is not secure! Please enable SSL and ensure your server has a valid SSL certificate.', 'woocommerce'), admin_url('admin.php?page=settings')).'</p></div>';

		}
		

		// CURL check
		function curl_check() {

			if ( !function_exists( 'curl_init' ) ) 
				echo '<div class="error"><p>' . __('PayPal Payflow Pro requires PHP CURL to be enabled on your hosting server. Contact your hosting company for assistance.', 'woocommerce') . '</p></div>';

		}

		    
		// Form fields
		function init_form_fields() {
		
		    $this->form_fields = array(

			'enabled' => array(
							'title' => __( 'Enable/Disable', 'woocommerce' ), 
							'label' => __( 'Enable PayPal Payflow Pro', 'woocommerce' ), 
							'type' => 'checkbox', 
							'description' => '', 
							'default' => 'no'
						), 
			'title' => array(
							'title' => __( 'Title', 'woocommerce' ), 
							'type' => 'text', 
							'description' => __( 'This controls the payment type title shown to the user during checkout.', 'woocommerce' ), 
							'default' => __( 'Credit card (PayPal Payflow Pro)', 'woocommerce' )
						), 
			'description' => array(
							'title' => __( 'Description', 'woocommerce' ), 
							'type' => 'textarea', 
							'description' => __( 'This controls the payment method description shown to the user during checkout.', 'woocommerce' ), 
							'default' => 'Pay with your credit card via PayPal Payflow Pro.'
						),  
			'partnername' => array(
							'title' => __( 'Partner Name', 'woocommerce' ), 
							'type' => 'text', 
							'description' => __( 'The ID provided to you by the authorized PayPal Reseller who registered you for the Payflow SDK. If you purchased your account directly from PayPal, use "PayPal".', 'woocommerce' ), 
							'default' => ''
						), 
			'username' => array(
							'title' => __( 'User Name', 'woocommerce' ), 
							'type' => 'text', 
							'description' => __( 'If you set up one or more additional users on the Payflow Pro account, this value is the of the user authorized to process transactions. If, however, you have not set up additional users on the account, set username to the same value as vendorname.', 'woocommerce' ), 
							'default' => ''
						), 
			'password' => array(
							'title' => __( 'Password', 'woocommerce' ), 
							'type' => 'password', 
							'description' => __( 'The password that you defined while registering for the Payflow Pro account.', 'woocommerce' ), 
							'default' => ''
						), 

			'vendorname' => array(
							'title' => __( 'Vendor Name or User Name', 'woocommerce' ), 
							'type' => 'text', 
							'description' => __( 'Your merchant login ID that you created when you registered for the account.', 'woocommerce' ), 
							'default' => ''
						),
			'cardtypes'	=> array(
							'title' => __( 'Accepted Cards', 'woocommerce' ), 
							'type' => 'multiselect', 
							'description' => __( 'Select which credit card types to accept. To select multiple card types hold down the Shift key while clicking the card type names.', 'woocommerce' ), 
							'default' => '',
							'options' => array(
								'Visa' => 'Visa',
								'MasterCard' => 'MasterCard', 
								'Discover' => 'Discover',
								'American Express' => 'American Express'
								),
						),		
			'cvv' => array(
							'title' => __( 'CVV', 'woocommerce' ), 
							'label' => __( 'Require customers to enter the credit card CVV code. Strongly recommended to help prevent fraud!', 'woocommerce' ), 
							'type' => 'checkbox', 
							'description' => __( '', 'woocommerce' ), 
							'default' => 'no'
						),
			'processing_type' => array(
							'title' => __( 'Processing Mode', 'woocommerce' ), 
							'label' => __( 'Processing Mode', 'woocommerce' ), 
							'type' => 'select', 
							'description' => __( 'Choose whether to only authorize transactions and not capture funds (you must capture funds manually) OR authorize and capture funds in one transaction. ', 'woocommerce' ), 
							'default' => 'auth_cap',
							'options' => array( 'auth' => 'Authorize Only', 'auth_cap' => 'Authorize and Capture' ),
						), 
			'testmode' => array(
							'title' => __( 'PayPal Payflow Pro Test Mode', 'woocommerce' ), 
							'label' => __( 'Enable Test Mode', 'woocommerce' ), 
							'type' => 'checkbox', 
							'description' => __( 'Enable test mode. This causes the gateway to process payments through PayPal\'s development server.', 'woocommerce' ), 
							'default' => 'no'
						), 
			'debug' => array(
							'title' => __( 'Debugging', 'woocommerce' ), 
							'label' => __( 'Enable debug emails', 'woocommerce' ), 
							'type' => 'checkbox', 
							'description' => __( 'Enabled debug messages via email. Only works in <strong>Test Mode</strong>.', 'woocommerce' ), 
							'default' => 'no'
						),
			'debugrecipient' => array(
							'title' => __( 'Debugging Email', 'woocommerce' ), 
							'type' => 'text', 
							'description' => __( 'The email address that will receive debugging messages when debug mode is on.', 'woocommerce' ), 
							'default' =>  get_option('admin_email')
						),
			);

		}
		
		

		// Admin area
		public function admin_options() {
		?>

			<h3><?php _e('PayPal Payflow Pro','woocommerce'); ?></h3>

			<p><?php _e( 'PayPal Payflow Pro works by adding credit card fields on the checkout and then sending the details to PayPal Payflow Pro for verification.', 'woocommerce' ); ?></p>

			<table class="form-table">

				<?php $this->generate_settings_html(); ?>

			</table>

		<?php

		}
		    
	    

		// Payment fields for public frontend
		function payment_fields() {
			?>
			<fieldset>

				<p class="form-row form-row-first">
					<label for="ccnum"><?php echo __("Credit Card number", 'woocommerce') ?> <span class="required">*</span></label>
					<input type="text" class="input-text" id="ccnum" name="ccnum" />
				</p>
		
				<p class="form-row form-row-last">
					<label for="cardtype"><?php echo __("Card type", 'woocommerce') ?> <span class="required">*</span></label>
					<select name="cardtype" id="cardtype" class="woocommerce-select">
						<?php foreach( $this->cardtypes as $key => $type ) { ?>
							<option value="<?php echo $key ?>"><?php _e( $type, 'woocommerce' ); ?></option>
						<?php } ?>
					</select>
				</p>
			
				<div class="clear"></div>

				<p class="form-row form-row-first">

					<label for="cc-expire-month"><?php echo __("Expiration date", 'woocommerce') ?> <span class="required">*</span></label>
					<select name="expmonth" id="expmonth" class="woocommerce-select woocommerce-cc-month">

						<option value=""><?php _e( 'Month', 'woocommerce' ) ?></option>

						<?php
							for ( $i = 1; $i <= 12; $i++ ) {

							    $m = substr( ( '0' . $i ), -2); 

							    echo '<option value="' . $m . '">' . $m . '</option>';

							}
						?>

					</select>

					<select name="expyear" id="expyear" class="woocommerce-select woocommerce-cc-year">

						<option value=""><?php _e( 'Year', 'woocommerce' ) ?></option>

						<?php
							for ( $i = date('y'); $i <= date( 'y' ) + 15; $i++ )
							    printf( '<option value="%u">20%u</option>', $i, $i );


						?>

					</select>

				</p>

				<?php if ( $this->cvv == 'yes' ) { ?>
				
					<p class="form-row form-row-last">
						<label for="cvv"><?php _e("Card security code", 'woocommerce') ?> <span class="required">*</span></label>
						<input type="text" class="input-text" id="cvv" name="cvv" maxlength="4" style="width:45px" />
					</p>

				<?php } ?>
				
				<div class="clear"></div>

			</fieldset>
			<?php  
		}

		/*
		function woocommerce_subscription_periods( $periods = '' ) { 

			unset( $periods['day'] );
			return $periods;

		}
		*/

		// Payment processor 
		function process_payment( $order_id ) {
			global $woocommerce;

			$order = &new woocommerce_order( $order_id );

			if ( $this->testmode != 'yes' ) 
				$txn['gateway_url'] = 'https://payflowpro.paypal.com';
			else
				$txn['gateway_url'] = 'https://pilot-payflowpro.paypal.com';


			$txn['PARTNER'] = $this->partnername;
			$txn['USER'] = $this->username;
			$txn['PWD'] = $this->password;
			$txn['VENDOR'] = $this->vendorname; //or your vendor name

			$txn['TENDER'] = 'C'; // C = credit card, P = PayPal 

			$txn['ACCT'] = str_replace( array( '-', ' ' ), '', $_POST['ccnum'] ); //cc number

			if ( $this->cvv ) { 
				$txn['CVV2'] = $_POST['cvv'];
			}

			$txn['EXPDATE'] = $_POST['expmonth'] . $_POST['expyear'];

			if ( 'auth_cap' == $this->processing_type )
			    $txn['TRXTYPE'] = 'S'; // S = sale, authorize and capture funds
			else 
			    $txn['TRXTYPE'] = 'A'; // A = authorize only, don't capture funds

			$txn['AMT'] = $order->order_total; //amount: 1 dollar

			$txn['CURRENCY'] = get_option( 'woocommerce_currency', false );

			$ip = $this->get_user_ip();

			if ( '' != $ip ) 
				$txn['CUSTIP'] = $ip;

			
			$txn['FIRSTNAME'] = $order->billing_first_name;
			$txn['LASTNAME'] = $order->billing_last_name;
			$txn['STREET'] = $order->billing_address_1;
			$txn['CITY'] = $order->billing_city;
			$txn['STATE'] = $order->billing_state;
			$txn['ZIP'] = $order->billing_postcode;
			$txn['COUNTRY'] = $order->billing_country;

			$txn['INVNUM'] = $order->id;

			$txn['EMAIL'] = $order->billing_email;

// Must set the plugin to Auth & Cap mode to collect payment immediately
// Cannot do daily subscription billings with PayFlow Pro

			/*

			if ( class_exists('WC_Subscriptions_Order') && WC_Subscriptions_Order::order_contains_subscription( $order ) ) {
			
				// It's a subscription
				$txn['TRXTYPE'] = 'R';

				$txn['ACTION'] = 'A'; // add a new subscription profile

				$txn['PROFILENAME'] = $txn['FIRSTNAME'] . ' ' . $txn['LASTNAME']; // profile identifier
			    
				$order_items = $order->get_items();
			    
				// Only one subscription allowed in the cart when PayPal Standard is active
				$product = $order->get_product_from_item( $order_items[0] );
			    
				$txn['DESC'] = $product->get_title();
			    
				$period = WC_Subscriptions_Order::get_subscription_period( $order );

				// Subscription unit of duration in PayPal Standard format
				switch( strtolower( $period ) ) {
				    case 'day':
					$txn['PAYPERIOD'] = 'WEEK'; // PayFlow Pro doesn't support DAY for subscriptions so override to make this "week"
					break;
				    case 'week':
					$txn['PAYPERIOD']  = 'WEEK';
					break;
				    case 'year':
					$txn['PAYPERIOD']  = 'YEAR';
					break;
				    case 'month':
				    default:
					$txn['PAYPERIOD']  = 'MONT';
					break;
				}

			    
				$txn['AMT'] = WC_Subscriptions_Order::get_price_per_period( $order );
			    
				$subscription_length = WC_Subscriptions_Order::get_subscription_length( $order );

   				$subscription_trial_length = WC_Subscriptions_Order::get_subscription_trial_length( $order );

				$sign_up_fee = WC_Subscriptions_Order::get_sign_up_fee( $order );

				// If signup fee and trial period, only charge the signup fee and not the first cycle payment
				// So set the start date to be when the trial ends
				if ( $sign_up_fee > 0 && $subscription_trial_length > 0 ) {

					$txn['OPTIONALTRX'] = 'S';

					$txn['OPTIONALTRXAMT'] = $sign_up_fee;

					$next_cycle = '+' . $subscription_trial_length . ' ' . $period; // e.g. +1 week

					$x = current_time( 'timestamp', false ). "\n";

					$txn['START'] = date('mdY', strtotime( $next_cycle , $x ) );

					// Reduce number of subscription periods
					if ( $subscription_length != 0 )
						$subscription_length--;

				// No signup, but there's a trial period, so set start date to be today + trial period length
				} else if ( !$sign_up_fee && $subscription_trial_length > 0 ) { 

					$next_cycle = '+' . $subscription_trial_length . ' ' . $period; // e.g. +1 month

					$x = current_time( 'timestamp', false ). "\n";

					$txn['START'] = date('mdY', strtotime( $next_cycle , $x ) );

					// Reduce number of subscription periods
					if ( $subscription_length != 0 )
						$subscription_length--;

				// No signup fee or trial period, so charge first reoccuring amt now, and set start date for next cycle
				} else { 

					$txn['OPTIONALTRX'] = 'S';

					$txn['OPTIONALTRXAMT'] = $txn['AMT'];

					$next_cycle = '+1 ' . $period; // e.g. +1 month

					$x = current_time( 'timestamp', false ). "\n";

					$txn['START'] = date('mdY', strtotime( $next_cycle , $x ) );

				}

				// If there is no trial period, charge for the signup fee plus the first cycle amount

				$txn['TERM'] = $subscription_length;

				$txn['MAXFAILPAYMENTS'] = 0; // cummulative fails before PayPal cancels the profile - zero means unlimited

				$txn['RETRYNUMDAYS'] = 32; // consecutive days in a row that PayPal tries to process failed payments


				if ( '' != trim ( $order->billing_company ) ) 
					$txn['COMPANYNAME'] = $order->billing_company;

			}
			*/
//var_dump($txn) ;die;
			$post = '';

			foreach( $txn as $key => $val ) {
				if ( 'gateway_url' != $key ) 
					$post .= urlencode($key) . '=' . urlencode($val) . '&';
			}

			$post = substr($post, 0, -1);

			$this->send_debugging_email( "URL: " . $txn['gateway_url']  . "\n\nSENDING REQUEST:" . print_r( $post, true ) );	

			
			$headers = array(
				'Content-Type' => 'text/namevalue',
				'X-VPS-REQUEST-ID' => uniqid(),
				'X-VPS-CLIENTTIMEOUT' => 45,
				'X-VPS-VITCLIENTCERTIFICATION-ID' => 'code generated guid',
				'X-VPS-VITINTEGRATION-PRODUCT' => 'WooCommerce Payflow Pro',
				'X-VPS-VITINTEGRATION-VERSION' => 0.1,
				'X-VPS-VIT-OS-NAME' => 'Windows XP',
				'X-VPS-VIT-OSVERSION' => 5.1,
				'X-VPS-VIT-RUNTIMEVERSION' => phpversion(),
			);

			$ch = curl_init();

			curl_setopt( $ch, CURLOPT_URL, $txn['gateway_url'] );
			curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
			curl_setopt( $ch, CURLOPT_HEADER, 0 );
			curl_setopt( $ch, CURLOPT_POST, 1 );
			curl_setopt( $ch, CURLOPT_POSTFIELDS, $post );
			curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
			curl_setopt( $ch, CURLOPT_TIMEOUT, 90 );
			curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 30 );
			curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 0 );
			curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, 0 );
			curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST,  0 ); 

			$response = curl_exec ($ch);
//var_dump($response);
			if ( $response === false )
				$cerr = curl_error(); 

			curl_close ($ch);

			if ( !is_array( $response ) ) { 
				$res = explode( '&', $response );
				$response = array();
				foreach( $res as $key => $val ) { 
					$out = explode( '=', $val );
					$response[ $out[0] ] = $out[1];
				}
			}

			if ( !is_array( $response ) ) {

					    $this->send_debugging_email( "PAYPAL PAYFLOW PRO ERROR:\n CURL Response:" . $cerr .$msg );
				    
					    $cancel_note = __('PayPal Payflow Pro payment failed', 'woocommerce') . ' CURL Error: ' . $cerr. ')';
		    
					    $order->add_order_note( $cancel_note );
					    
					    $woocommerce->add_error(__('Payment error', 'woocommerce') . ': CURL Error: ' . $cerr . '');

			} else { 

/*
//var_dump($response);
//payflowpro.php
array(8) { ["RESULT"]=> string(1) "0" ["PNREF"]=> string(12) "V35P1E2AC39C" ["RESPMSG"]=> string(8) "Approved" ["AUTHCODE"]=> string(6) 
"020301" ["AVSADDR"]=> string(1) "Y" ["AVSZIP"]=> string(1) "N" ["CVV2MATCH"]=> string(1) "Y" ["IAVS"]=> string(1) "N" } 
*/
				switch ( intval( $response['RESULT'] ) ) {

				    // Approved

				    case 0:

						/*******
					    if ( isset( $response['AVSADDR'] ) ) {
						if ( $response['AVSADDR'] != 'Y' ) { 
							$msg = __('Your billing information does not match.  Please re-enter.', 'woocommerce' );
							$oops = true;
						}
					    }

					    // Verify zip
					    if ( isset( $response['AVSZIP'] ) ) {

						if ( $response['AVSZIP'] != 'Y' ) {
							$msg = __('Your billing information does not match.  Please re-enter.', 'woocommerce' );
							$oops = true;
						}

					    }
						******/

					    // Verify CVV2 code
					    if ( 'yes' == $this->cvv && isset( $response['CVV2MATCH'] ) ) {

						if ( $response['CVV2MATCH'] != 'Y' ) {
							$msg = __('Your billing information does not match. Please re-enter.', 'woocommerce' );
							$oops = true;
						}

					    }

					    if ( !$oops )  {

						    // Payment complete
		    
						    $order->add_order_note( __( 'PayPal Payflow Pro payment completed:', 'woocommerce') . ' (PayFlow Transaction ID: ' . $response['PNREF'] . ')' . ' (Unique Transaction ID: ' . $response['PPREF'] . ')');

						    // Subscription order? If so then record the profile ID
						    if ( isset( $response['PROFILEID'] ) && '' != $response['PROFILEID'] ) {
							    $order->add_order_note( __( 'PayPal Payflow Pro - Subscription Profile ID:', 'woocommerce') . $response['PROFILEID'] );
							    update_post_meta( $order_id, 'paypal_subscription_profile_id', $response['PROFILEID'] );
						    }


						    $order->payment_complete();

						    //if ( class_exists( 'WC_Subscriptions_Manager' ) ) 
							//    WC_Subscriptions_Manager::activate_subscriptions_for_order( $order );
			    
						    $woocommerce->cart->empty_cart();

						    // Empty awaiting payment session var
						    unset($_SESSION['order_awaiting_payment']);
							    
						    // Return thank you redirect
						    return array(
							    'result' 	=> 'success',
							    'redirect'	=> add_query_arg('key', $order->order_key, add_query_arg('order', $order_id, get_permalink(get_option('woocommerce_thanks_page_id'))))
						    );

					    } else {
						    
						    $this->send_debugging_email( "PAYPAL PAYFLOW PRO ERROR:\nresponse_code:" . $response['RESULT'] . "\nresponse_reasib_text:" .$msg );
					    
						    $cancel_note = __('PayPal Payflow Pro payment failed', 'woocommerce') . ' (Response Code: ' . $response['RESULT'] . '). ' . __('Payment was rejected due to an error', 'woocommerce') . ': "' . $msg. '". ';
			    
						    $order->add_order_note( $cancel_note );
						    
						    $woocommerce->add_error(__('Payment error', 'woocommerce') . ': ' . $msg . '');

					    }


				    // Account configuration issue
				    case 1:
				    // Invalid vendor account
				    case 26:
					    $cancel_note = __('PayPal Payflow Pro payment failed', 'woocommerce') . ' (Response Code: ' . $response['RESULT'] . '). ' . __('Payment was rejected due to an error', 'woocommerce') . ': "' . $response['RESPMSG'] . '". ';
					    $order->add_order_note( $cancel_note );
					    $msg = __( 'Invalid Payflow Pro account configuration.', 'woocommerce' );
					    $woocommerce->add_error( __('Payment error', 'woocommerce') . ': ' . $msg . '');
					    break;


				    // Declined from bank
				    case 12:
				    // Issue with credit card number
				    case 23:
				    // Issue with expiration date
				    case 24:
					    $cancel_note = __('PayPal Payflow Pro payment failed', 'woocommerce') . ' (Response Code: ' . $response['RESULT'] . '). ' . __('Payment was rejected due to an error', 'woocommerce') . ': "' . $response['RESPMSG'] . '". ';
					    $order->add_order_note( $cancel_note );
					    $msg = __( 'Transaction declined:', 'woocommerce' );
					    $msg .= $response['RESPMSG'];
					    $woocommerce->add_error( __('Payment error', 'woocommerce') . ': ' . $msg . '');
					    break;


				    // Voice authorization required
				    case 13:
					    $cancel_note = __('PayPal Payflow Pro payment failed', 'woocommerce') . ' (Response Code: ' . $response['RESULT'] . '). ' . __('Payment was rejected due to an error', 'woocommerce') . ': "' . $response['RESPMSG'] . '". ';
					    $order->add_order_note( $cancel_note );
					    $msg = __( 'Transaction pending:', 'woocommerce' );
					    $msg .= $response['RESPMSG'];
					    $woocommerce->add_error( __('Payment error', 'woocommerce') . ': ' . $msg . '');
					    break;

				    case 112:
					    $cancel_note = __('PayPal Payflow Pro payment failed', 'woocommerce') . ' (Response Code: ' . $response['RESULT'] . '). ' . __('Payment was rejected due to an error', 'woocommerce') . ': "' . $response['RESPMSG'] . '". ';
					    $order->add_order_note( $cancel_note );
					    $msg = __( 'Error: Address and Zipcode do not match.', 'woocommerce' );
					    $woocommerce->add_error( __('Payment error', 'woocommerce') . ': ' . $msg . '');
					    break;

				    case 114:
					    $cancel_note = __('PayPal Payflow Pro payment may have failed', 'woocommerce') . ' (Response Code: ' . $response['RESULT'] . '). ' . __('Payment was rejected due to an error', 'woocommerce') . ': "' . $response['RESPMSG'] . '". ';
					    $order->add_order_note( $cancel_note );
					    $msg = __( 'Error: Card security code is not correct.', 'woocommerce' );
					    $woocommerce->add_error( __('Payment error', 'woocommerce') . ': ' . $msg . '');
					    break;

				    // Declined by filters
				    case 125:
					    $cancel_note = __('PayPal Payflow Pro payment failed', 'woocommerce') . ' (Response Code: ' . $response['RESULT'] . '). ' . __('Payment was rejected due to an error', 'woocommerce') . ': "' . $response['RESPMSG'] . '". ';
					    $order->add_order_note( $cancel_note );
					    $msg = __( 'Transaction declined:', 'woocommerce' );
					    $msg .= $response['RESPMSG'];
					    $woocommerce->add_error( __('Payment error', 'woocommerce') . ': ' . $msg . '');
					    break;

				    // Flagged for review by filters
				    case 126:
					    $cancel_note = __('PayPal Payflow Pro payment REVIEW REQUIRED - You MUST review the transaction in your Payflow Pro account and manually accept it', 'woocommerce') . ' (Response Code: ' . $response['RESULT'] . '). ' . __('Payment was rejected due to an error', 'woocommerce') . ': "' . $response['RESPMSG'] . '". TRANSACTION ID:' .$response['PNREF']. ' AUTH CODE: ' . $response['AUTHCODE'];                      
					    $order->add_order_note( $cancel_note );
					    //$msg = __( 'Transaction under review:', 'woocommerce' );
					    //$msg .= $response['RESPMSG'];
					    //$woocommerce->add_error( __('Payment error', 'woocommerce') . ': ' . $msg . '');
					    // Transaction accepted but not complete
	    
					    $order->update_status( 'pending' );
		    
					    $woocommerce->cart->empty_cart();

					    // Empty awaiting payment session
					    unset($_SESSION['order_awaiting_payment']);

					    //if ( class_exists( 'WC_Subscriptions_Manager' ) )
						//    WC_Subscriptions_Manager::failed_subscription_sign_ups_for_order( $order );
						    
					    // Return thank you redirect
					    return array(
						    'result' 	=> 'success',
						    'redirect'	=> add_query_arg('key', $order->order_key, add_query_arg('order', $order_id, get_permalink(get_option('woocommerce_thanks_page_id'))))
					    );
					    break;

				    // Not processed by filters
				    case 127:
					    $cancel_note = __('PayPal Payflow Pro payment failed', 'woocommerce') . ' (Response Code: ' . $response['RESULT'] . '). ' . __('Payment was rejected due to an error', 'woocommerce') . ': "' . $response['RESPMSG'] . '". ';
					    $order->add_order_note( $cancel_note );
					    $msg = __( 'Transaction under review:', 'woocommerce' );
					    $msg .= $response['RESPMSG'];
					    $woocommerce->add_error( __('Payment error', 'woocommerce') . ': ' . $msg . '');
					    break;

				    // Generic error for all results not captured above
				    default:
					    $cancel_note = __('PayPal Payflow Pro payment failed', 'woocommerce') . ' (Response Code: ' . $response['RESULT'] . '). ' . __('Payment was rejected due to an error', 'woocommerce') . ': "' . $response['RESPMSG'] . '". ';
					    $order->add_order_note( $cancel_note );
					    $msg = __( 'Processing error:', 'woocommerce' );
					    $msg .= $response['RESPMSG'];
					    $woocommerce->add_error( __('Payment error', 'woocommerce') . ': ' . $msg . '');
					    break;
				}


				//if ( class_exists( 'WC_Subscriptions_Manager' ) )
				//	WC_Subscriptions_Manager::failed_subscription_sign_ups_for_order( $order );


				$this->send_debugging_email( "\n\nRESPONSE:" . print_r($response,true));	

			}


		}

		/*
		function cancel_subscription( $order, $product_id ) { 

			$profile_id = get_post_meta( $order->id, 'paypal_subscription_profile_id', true );

			if ( !$profile_id )
				return;

			if ( $this->testmode != 'yes' ) 
				$txn['gateway_url'] = 'https://payflowpro.paypal.com';
			else
				$txn['gateway_url'] = 'https://pilot-payflowpro.paypal.com';


			$txn = array();

			$txn['PARTNER'] = $this->partnername;
			$txn['USER'] = $this->username;
			$txn['PWD'] = $this->password;
			$txn['VENDOR'] = $this->vendorname; //or your vendor name

			$txn['TRXTYPE'] = 'R';
			$txn['TENDER'] = 'C'; 
			$txn['ORIGPROFILEID'] = $profile_id; 

			$headers = array(
				'Content-Type' => 'text/namevalue',
				'X-VPS-REQUEST-ID' => uniqid(),
				'X-VPS-CLIENTTIMEOUT' => 45,
				'X-VPS-VITCLIENTCERTIFICATION-ID' => 'code generated guid',
				'X-VPS-VITINTEGRATION-PRODUCT' => 'WooCommerce Payflow Pro',
				'X-VPS-VITINTEGRATION-VERSION' => 0.1,
				'X-VPS-VIT-OS-NAME' => 'Windows XP',
				'X-VPS-VIT-OSVERSION' => 5.1,
				'X-VPS-VIT-RUNTIMEVERSION' => phpversion(),
			);

			$post = '';

			foreach( $txn as $key => $val ) {
				if ( 'gateway_url' != $key ) 
					$post .= urlencode($key) . '=' . urlencode($val) . '&';
			}

			$ch = curl_init();

			curl_setopt( $ch, CURLOPT_URL, $txn['gateway_url'] );
			curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
			curl_setopt( $ch, CURLOPT_HEADER, 0 );
			curl_setopt( $ch, CURLOPT_POST, 1 );
			curl_setopt( $ch, CURLOPT_POSTFIELDS, $post );
			curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
			curl_setopt( $ch, CURLOPT_TIMEOUT, 90 );
			curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 30 );
			curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 0 );
			curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, 0 );
			curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST,  0 ); 

			$response = curl_exec ($ch);

			if ( $response === false )
				$cerr = curl_error(); 

			curl_close ($ch);

			if ( !is_array( $response ) ) { 
				$res = explode( '&', $response );
				$response = array();
				foreach( $res as $key => $val ) { 
					$out = explode( '=', $val );
					$response[ $out[0] ] = $out[1];
				}
			}

			if ( !is_array( $response ) ) {

				$this->send_debugging_email( "PAYPAL PAYFLOW PRO ERROR:\n CURL Response:" . $cerr .$msg );
			
				$cancel_note = __('PayPal Payflow Pro subscription cancellation failed', 'woocommerce') . ' CURL Error: ' . $cerr. ')';
	
				$order->add_order_note( $cancel_note );

			} else if ( 0 != $response['RESULT'] ) { 

				$cancel_note = __('PayPal Payflow Pro subscription cancellation failed', 'woocommerce') . ' ERROR #' . $response['RESULT'];

				if ( '' != $response['RESPMSG'] )
					$cancel_note .= ' - ' . $response['RESPMSG'];
	
				$order->add_order_note( $cancel_note );


			} else if ( 0 == $response['RESULT'] ) { 

				$cancel_note = __('PayPal Payflow Pro subscription cancelled', 'woocommerce');
	
				$order->add_order_note( $cancel_note );

				WC_Subscriptions_Manager::cancel_subscriptions_for_order( $order );

			}


		}
		*/

		function get_user_ip() { 

			if (isset($_SERVER["HTTP_CLIENT_IP"]))
				return $_SERVER["HTTP_CLIENT_IP"];
				
			elseif (isset($_SERVER["HTTP_X_FORWARDED_FOR"]))			
				return $_SERVER["HTTP_X_FORWARDED_FOR"];
			
			elseif (isset($_SERVER["HTTP_X_FORWARDED"]))
				return $_SERVER["HTTP_X_FORWARDED"];
			
			elseif (isset($_SERVER["HTTP_FORWARDED_FOR"]))
				return $_SERVER["HTTP_FORWARDED_FOR"];
			
			elseif (isset($_SERVER["HTTP_FORWARDED"]))
				return $_SERVER["HTTP_FORWARDED"];

			else
				return $_SERVER["REMOTE_ADDR"];

		}



		// Validate form field data
		public function validate_fields() {
			global $woocommerce;

			$cardType = $this->get_post('card_type');
			$cardNumber = $this->get_post('ccnum');
			$cardCSC = $this->get_post('cvv');
			$cardExpirationMonth = $this->get_post('expmonth');
			$cardExpirationYear = $this->get_post('expyear');
		
			if ( $this->cvv=='yes' ) {

				//check security code
				if( !ctype_digit( $cardCSC ) ) {
					$woocommerce->add_error( __( 'Card security code is invalid (only digits are allowed)', 'woocommerce' ) );
					return false;
				}
		
				if( (strlen( $cardCSC ) != 3 && in_array( $cardType, array('Visa', 'MasterCard', 'Discover') ) ) || ( strlen( $cardCSC ) != 4 && $cardType == 'American Express' ) ) {
					$woocommerce->add_error( __( 'Card security code is invalid (wrong length)', 'woocommerce' ) );
					return false;
				}
			}


			//check expiration data
			$currentYear = date('y');

			if( !ctype_digit( $cardExpirationMonth ) || !ctype_digit( $cardExpirationYear ) ||
				    $cardExpirationMonth > 12 ||
				    $cardExpirationMonth < 1 ||
				    $cardExpirationYear < $currentYear ||
				    $cardExpirationYear > $currentYear + 15
			) {
				$woocommerce->add_error( __( 'Card expiration date is invalid', 'woocommerce' ) );
				return false;
			}


			//check card number
			$cardNumber = str_replace( array( ' ', '-' ), '', $cardNumber );

			if ( empty( $cardNumber ) || !ctype_digit( $cardNumber ) ) {
				$woocommerce->add_error( __( 'Card number is invalid', 'woocommerce' ) );
				return false;
			}

			return true;
		}


		// Message for receipt page
		function receipt_page( $order ) {
			
			echo '<p>'.__( 'Thank you for your order.', 'woocommerce' ).'</p>';
			
		}
		

		// Retrieve some post data
		private function get_post($name) {

			if( isset( $_POST[$name] ) )
				return $_POST[$name];

			return NULL;

		}



		// Debug message delivery 
		function send_debugging_email( $debug ) {
			
			if ( $this->debug != 'yes' ) return; // Debug must be enabled

			if ( $this->testmode!='yes' ) return; // Test mode required

			if ( !$this->debugrecipient ) return; // Recipient needed

			wp_mail( $this->debugrecipient, __( 'PayPal Payflow Pro Debug', 'woocommerce' ), $debug );
			
		} 


	} // end class	

}
?>